#include "diskmanager.h"
#include "constants.h"
#include <QDebug>
#include <QDir>
#ifdef Q_OS_WIN32
#include <windows.h>
#else
#include <sys/statvfs.h>
#endif

bool DiskManager::isDir(const QString &path)
{
    QFileInfo fileInfo(path);
    return fileInfo.isDir();
}

bool DiskManager::fileExists(const QString &path)
{
    return QFile::exists(path);
}

bool DiskManager::dirExists(const QString &path)
{
    return QDir(path).exists(path);
}

bool DiskManager::mkdir(const QString &path)
{
    bool ret = true;
    QDir dir(path);
    if (!dir.exists(path)) {
        ret = dir.mkdir(path);
    }

    return ret;
}

bool DiskManager::copyFile(const QString &srcPath, const QString &dstPath, bool coverFileIfExist)
{
    QString srcFile = srcPath;
    QString dstFile = dstPath;
    srcFile.replace("\\", "/");
    dstFile.replace("\\", "/");
    if (srcPath == dstFile) {
        return true;
    }

    if (!QFile::exists(srcFile)) {
        return false;
    }

    if (QFile::exists(dstFile)) {
        if (coverFileIfExist) {
            QFile::remove(dstFile);
        }
    }

    if (!QFile::copy(srcFile, dstFile)) {
        return false;
    }
    return true;
}

bool DiskManager::copyDirectory(const QString &srcPath, const QString &dstPath, bool coverFileIfExist)
{
    QDir srcDir(srcPath);
    QDir dstDir(dstPath);
    if (!dstDir.exists()) { //目的文件目录不存在则创建文件目录
        if (!dstDir.mkdir(dstDir.absolutePath()))
            return false;
    }

    QFileInfoList fileInfoList = srcDir.entryInfoList();
    foreach(QFileInfo fileInfo, fileInfoList) {
        if (fileInfo.fileName() == "." || fileInfo.fileName() == "..")
            continue;

        if (fileInfo.isDir()) { //当为目录时，递归
            if (!copyDirectory(fileInfo.filePath(),dstDir.filePath(fileInfo.fileName()),coverFileIfExist))
                return false;
        }
        else { //当允许覆盖操作时，将旧文件进行删除操作
            if (coverFileIfExist && dstDir.exists(fileInfo.fileName())) {
                dstDir.remove(fileInfo.fileName());
            }
            //文件copy
            if (!QFile::copy(fileInfo.filePath(), dstDir.filePath(fileInfo.fileName()))) {
                return false;
            }
        }
    }
    return true;
}

bool DiskManager::deleteFile(const QString &path)
{
    bool ret = true;
    if (QFile::exists(path))
    {
        ret = QFile::remove(path);
    }

   return ret;
}

bool DiskManager::deleteDirectory(const QString &path)
{
    bool ret = true;
    QDir dir(path);
    if (dir.exists())
    {
        ret = dir.removeRecursively();
    }

    return ret;
}

bool DiskManager::deleteEmptyDirectory(const QString &path)
{
    bool ret = true;
    QDir dir(path);
    if (dir.exists())
    {
        ret = dir.rmdir(path);
    }

    return ret;
}

QString DiskManager::toNormalizedPath(const QString &path)
{
    QString absolutePath = QDir(path).absolutePath();
    QString stdpath = QDir::toNativeSeparators(absolutePath);
    return stdpath;
}

quint64 DiskManager::getFreeSpace(const QString &driver)
{
#if defined(Q_OS_WIN32)
    LPCWSTR lpcwstrDriver = (LPCWSTR)driver.utf16();
    ULARGE_INTEGER liFreeBytesAvailable, liTotalBytes, liTotalFreeBytes;
    if (!GetDiskFreeSpaceEx(lpcwstrDriver, &liFreeBytesAvailable, &liTotalBytes, &liTotalFreeBytes)) {
        qDebug() << "error: GetDiskFreeSpaceEx() failed.";
        return 0;
    }

    return (quint64)liTotalFreeBytes.QuadPart / 1024 / 1024;
#else
    int state;
    struct statvfs vfs;
    fsblkcnt_t block_size = 0;
    fsblkcnt_t free_size;

    state = statvfs(driver.toStdString().data(), &vfs);
    if (state < 0) {
        qDebug("error: statvfs() failed.");
        return 0;
    }

    block_size = vfs.f_bsize;
    free_size = vfs.f_bavail * block_size;
    return free_size / 1024 / 1024;
#endif
}
